package com.mi.rof.engineer.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.mi.rof.engineer.service.SmsService;
import com.mi.rof.entity.RepairOrder;
import com.mi.rof.engineer.entity.RepairOrderEvents;
import com.mi.rof.engineer.entity.RepairOrderStates;
import com.mi.rof.engineer.service.RepairOrderService;
import com.mi.rof.entity.SystemException;
import com.mi.rof.entity.enums.ExceptionEnum;
import com.mi.rof.user.entity.UserTable;
import com.mi.rof.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.Message;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.EnableWithStateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.state.State;
import org.springframework.statemachine.support.DefaultStateMachineContext;
import org.springframework.statemachine.support.StateMachineInterceptorAdapter;
import org.springframework.statemachine.transition.Transition;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Optional;

@Service
@Slf4j
@EnableWithStateMachine
public class RepairStateMachineBuild {

    @Resource
    private RepairOrderService repairOrderService;

    @Resource
    private UserService userService;

    @Resource
    private SmsService smsService;

    private StateMachineFactory<RepairOrderStates, RepairOrderEvents> factory;

    private static final String ORDER_ID_HEADER = "orderId";
    private static final String COMPANY = "小米科技有限公司";
    private static final String HOTLINE = "027-1234567";

    public RepairStateMachineBuild(StateMachineFactory<RepairOrderStates, RepairOrderEvents> factory) {
        this.factory = factory;
    }

    public StateMachine<RepairOrderStates, RepairOrderEvents> build(String orderId) {
        RepairOrder order = repairOrderService.findRepairOrderById(orderId);
        String orderIdKey = order.getRepairOrderId();
        StateMachine<RepairOrderStates, RepairOrderEvents> stateMachine =
                this.factory.getStateMachine(String.valueOf(orderIdKey));

        stateMachine.stop();

        stateMachine.getStateMachineAccessor()
                .doWithAllRegions(sma -> {
                    sma.addStateMachineInterceptor(new StateMachineInterceptorAdapter<RepairOrderStates, RepairOrderEvents>() {

                        @Override
                        public void preStateChange(State<RepairOrderStates, RepairOrderEvents> state,
                                                   Message<RepairOrderEvents> message,
                                                   Transition<RepairOrderStates, RepairOrderEvents> transition,
                                                   StateMachine<RepairOrderStates, RepairOrderEvents> stateMachine,
                                                   StateMachine<RepairOrderStates, RepairOrderEvents> rootStateMachine) {
                            Optional.ofNullable(message).ifPresent(msg -> {
                                Optional.ofNullable(String.valueOf(msg.getHeaders().getOrDefault(ORDER_ID_HEADER, 1)))
                                        .ifPresent(orderId -> {
                                            RepairOrder orderOld = repairOrderService.findRepairOrderById(orderId);
                                            orderOld.setState(state.getId().getCode());
                                            repairOrderService.updateRepairOrder(orderOld);
                                        });
                            });
                        }

                        @Override
                        public void postStateChange(State<RepairOrderStates, RepairOrderEvents> state, Message<RepairOrderEvents> message,
                                                    Transition<RepairOrderStates, RepairOrderEvents> transition,
                                                    StateMachine<RepairOrderStates, RepairOrderEvents> stateMachine,
                                                    StateMachine<RepairOrderStates, RepairOrderEvents> rootStateMachine) {
                            String orderId = (String) message.getHeaders().get(RepairOrderStateServiceImpl.ORDER_ID_HEADER);
                            RepairOrder repairOrder = repairOrderService.findRepairOrderById(orderId);
                            if(ObjectUtil.isNull(repairOrder)){
                                throw new SystemException(ExceptionEnum.ORDER_NOT_EXIST.getCode(), ExceptionEnum.ORDER_NOT_EXIST.getMsg());
                            }
                            UserTable normalUser = userService.getNormalUser(repairOrder.getUserId());
                            if(ObjectUtil.isNull(normalUser)){
                                throw new SystemException(ExceptionEnum.USER_NOT_EXIST.getCode(), ExceptionEnum.USER_NOT_EXIST.getMsg());
                            }
                            String userNotify = String.format(
                                    "亲爱的客户，您好！\n" +
                                            "您的设备（维修单号：%s）目前的维修进度如下：\n" +
                                            "维修状态已变更为：%s\n" +
                                            "如有任何问题，请随时联系我们的客服热线：%s。\n" +
                                            "感谢您的耐心等待！\n" +
                                            "祝您生活愉快！\n" +
                                            "%s",repairOrder.getRepairOrderId(),state.getId().getMsg(),HOTLINE,COMPANY);
                             log.info("发送短信通知：{}",userNotify);
                             //发送短信通知
                            super.postStateChange(state, message, transition, stateMachine, rootStateMachine);
                        }

                    });

                    sma.resetStateMachine(
                            new DefaultStateMachineContext<>(
                                    RepairOrderStates.getByCode(order.getState()),
                                    null,
                                    null,
                                    null)
                    );
                });

        stateMachine.start();
        return stateMachine;
    }
}
